function [prm]=bciParadigmControl(bci,action,prm)
% controls the stimulus and its parameters
% bci.paradigm.id - 1 = cursor task
%                2 = continuos robot arm task
%                3 = event related robot arm task

switch bci.paradigm.id,
    case 1,
        prm=bciParadigmID1(bci,action,prm);
    case 2,
        prm=bciParadigmID2(bci,action,prm);
    case 3,
        prm=bciParadigmID3(bci,action,prm);
    case 4,
        prm=bciParadigmID4(bci,action,prm);
    otherwise
        warning('Paradigm ID not defined in bciParadigmControl');
end
% general train mode settings
if prm.mode==0 && strcmp(action,'init'),
    prm.hitTarget= true;
end


% paradigm dependent functions
% ------- Cursor Task
function prm=bciParadigmID1(bci,action,prm)
if strcmp(action,'move'),
    % how many samples to use for prediction?
    nPred = length(prm.predictedInTrial);
    maxPred = min(nPred,max(1,round(bci.param.winsrate / bci.predictionRate)));
    predIdx = nPred-maxPred+1:nPred;
    % determine prediction using samples of last 1/bci.predictionRate
    predCount(bci.leftEvent)=sum(prm.predictedInTrial(predIdx)==bci.leftEvent);
    predCount(bci.baseEvent)=sum(prm.predictedInTrial(predIdx)==bci.baseEvent);
    predCount(bci.rightEvent)=sum(prm.predictedInTrial(predIdx)==bci.rightEvent);
    [dummy, prm.mostPred]=max(predCount);
    if length(bci.eventsToClassify)<3 && prm.mostPred==bci.baseEvent,
        % in two class case move backward instead of baseCond
        prm.mostPred = setdiff([bci.leftEvent,bci.rightEvent],bci.eventsToClassify);
    end
    if sum(predCount==dummy)>1, %if multiple maxima dont move
        prm.mostPred = bci.baseEvent;
    end
    prm.predCount=[0 0 0];
    
    if prm.mostPred==bci.rightEvent, % move right
        prm.cursorPos=min(0.99,prm.cursorPos+prm.stepSize);
    elseif prm.mostPred==bci.leftEvent; % move left
        prm.cursorPos=max(0.01,prm.cursorPos-prm.stepSize);
    end
    set(prm.txtCursor,'position',[prm.cursorPos,0.5,0]);
    prm.hitTarget = abs(prm.cursorPos-prm.targetPos)<prm.stepSize;
    prm.hitSuccess = prm.hitTarget;
    drawnow;
elseif strcmp(action,'init'),
    % Set up display
    bgColor=[0.8 0.8 0.8];
    screenSize=get(0,'ScreenSize');
    % screenSize=[5   575   560   420]; % window in upper left corner
    prm.FH = figure('Position',screenSize,'MenuBar','none',...
        'Pointer','circle','color',bgColor);
    prm.AH=axes('position',[0 0 1 1],'color',bgColor,'FontName','Courier','FontSize', 30,...
        'xtick',[],'ytick',[],'xlim',[0 1],'ylim',[0 1]);

    % show stat screen
    if prm.mode==0,
        prm.TH=title(prm.AH,'Starting soon...');
    else
        prm.TH=title(prm.AH,'Hit the Cross...');
        prm.targetPos = 0.2;
        prm.cursorPos = 0.5;
        prm.txtTarget=text(prm.targetPos,0.5,'+','color',[1 1 1],'fontsize',15,'visible','off');
        prm.txtCursor=text(prm.cursorPos,0.5,'o','color',[1 1 1],'fontsize',15,'visible','off');
        prm.systemRorL([bci.leftEvent bci.rightEvent])=[0.1 0.9];
        prm.mostPred=2;
        prm.stepSize = bci.cursorSpeed/bci.cursorRate;
    end
    titlePos=get(prm.TH,'position');
    titlePos(1:2)=[0.5,0.5];
    set(prm.TH,'color',[1 1 1],'position',titlePos);
    drawnow;
    prm.trialClassified = false;
elseif strcmp(action,'newevent')
    eventStr = {'<--','+','-->','Finished.','Pause.','Attention!','Attention!'}; % outputs linked to event ID
    set(prm.TH,'string',eventStr(prm.curEvent));
    drawnow;
elseif strcmp(action,'newtarget')
    prm.cursorPos=0.5;
    prm.targetPos = prm.systemRorL(prm.curEvent);
    % set new target
    set(prm.txtTarget,'position',[prm.targetPos,0.5,0],'visible','on');
    set(prm.txtCursor,'position',[prm.cursorPos,0.5,0],'visible','on');
    set(prm.TH,'visible','off');
    drawnow;
elseif strcmp(action,'hide')
    set([prm.txtTarget,prm.txtCursor],'visible','off');
elseif strcmp(action,'finish')
    set(prm.TH,'string','Finished.');
end

% ------- Robotarm continuous control
function prm=bciParadigmID2(bci,action,prm)
if strcmp(action,'move'),
    if prm.mode==0,
    else
        % how many samples to use for prediction?
        nPred = length(prm.predictedInTrial);
        maxPred = min(nPred,max(1,round(bci.param.winsrate / bci.predictionRate)));
        predIdx = nPred-maxPred+1:nPred;
        % determine prediction using samples of last 1/bci.predictionRate
        predCount(bci.leftEvent)=sum(prm.predictedInTrial(predIdx)==bci.leftEvent);
        predCount(bci.baseEvent)=sum(prm.predictedInTrial(predIdx)==bci.baseEvent);
        predCount(bci.rightEvent)=sum(prm.predictedInTrial(predIdx)==bci.rightEvent);
        [dummy, prm.mostPred]=max(predCount);
        if length(bci.eventsToClassify)<3 && prm.mostPred==bci.baseEvent,
             % in two class case move backward instead of baseCond
             prm.mostPred = setdiff([bci.leftEvent,bci.rightEvent],bci.eventsToClassify);
        end                
        if sum(predCount==dummy)>1, %if multiple maxima dont move
            prm.mostPred = bci.baseEvent;
        end
        prm.predCount=[0 0 0];
       
        if prm.mostPred==prm.curEvent, % move forward
            prm.direction=1;
        elseif prm.mostPred==bci.baseEvent; % don't move
            prm.direction=0.000001;
        else % move backward
            prm.direction=-1;
        end
        setDirection(prm.direction);
        currentArmPosition=getPosition;
        prm.hitTarget = currentArmPosition>9995 || currentArmPosition<2600;
        if currentArmPosition>9995 ,
            prm.hitSuccess=true;
        end
    end
elseif strcmp(action,'init'),
    prm.systemVal=2;
    prm.armPos=5000;
    prm.restingVal=1e-12;% currently restingVal=0 doesn't work properly
    prm.destinationVal=10000; % destination position of arm
    prm.velocityToDestination = 0;  % set 1 if move to object, 0 otherwise,<1 for slow movement

    setArmSystem(prm.systemVal);
    setBallSystem(prm.systemVal);
    setDirection(prm.restingVal);
    if prm.mode==1,
        prm.systemRorL([bci.leftEvent bci.rightEvent])=[0 1];
        prm.mostPred=2;
    end
    prm.trialClassified = false;
elseif strcmp(action,'newevent')
    switch prm.curEvent,
        case bci.leftEvent,
            prm.armPos=prm.destinationVal-round(prm.velocityToDestination*prm.curEventDur*5000/10);%10000
            prm.armVelocity=prm.velocityToDestination;
            prm.systemVal=0;
            setBallSystem(prm.systemVal);
        case bci.rightEvent,
            prm.armPos=prm.destinationVal-round(prm.velocityToDestination*prm.curEventDur*5000/10);%10000
            prm.armVelocity=prm.velocityToDestination;
            prm.systemVal=1;
            setBallSystem(prm.systemVal);
        case bci.baseEvent,
            prm.armPos=5000;
            prm.armVelocity=prm.restingVal;
            setBallSystem(2);
            if prm.systemVal==2,
                prm.systemVal=1;
            end
        otherwise
            prm.systemVal=2;
            setBallSystem(2);
            prm.armVelocity=prm.restingVal;
    end
    setDirection(prm.restingVal);
    setArmSystem(prm.systemVal);
    setPosition(prm.armPos);
    % wait until position is set
    while abs(getPosition-prm.armPos)>10,pause(0.001);end
    setDirection(prm.armVelocity);
    %prm.hitTarget=false;
elseif strcmp(action,'newtarget')
    prm.armPos=5000;
    prm.systemVal = prm.systemRorL(prm.curEvent);
    % set new target
    setDirection(prm.restingVal);
    setPosition(prm.armPos);
    % wait until position is set
    while abs(getPosition-prm.armPos)>10,pause(0.001);end
    setArmSystem(prm.systemVal);
    setBallSystem(prm.systemVal);
elseif strcmp(action,'hide')
    setDirection(prm.restingVal);
    setArmSystem(2);
    setBallSystem(2);
    setPosition(5000);
    % wait until position is set
    while abs(getPosition-5000)>10,pause(0.001);end
elseif strcmp(action,'finish')
    setArmSystem(2);
    setBallSystem(2);
end

% ------- Robotarm event evoked control
function prm=bciParadigmID3(bci,action,prm)
if strcmp(action,'move'),
    if prm.mode>0 && length(prm.predictedInTrial)>=prm.nPredLocal&&~prm.trialClassified,
        % determine local prediction rate
        localPred=zeros(3,length(prm.predictedInTrial)-prm.nPredLocal+1);
        k=0;
        while prm.localPredCount<=length(prm.predictedInTrial)-prm.nPredLocal+1,
            k=k+1;
            idx = prm.localPredCount:prm.localPredCount+prm.nPredLocal-1;
            localPred(bci.leftEvent,k) = sum(prm.predictedInTrial(idx)==bci.leftEvent)/prm.nPredLocal;
            localPred(bci.baseEvent,k) = sum(prm.predictedInTrial(idx)==bci.baseEvent)/prm.nPredLocal;
            localPred(bci.rightEvent,k) = sum(prm.predictedInTrial(idx)==bci.rightEvent)/prm.nPredLocal;
            prm.localPredCount=prm.localPredCount+1;
        end
        [dummy, prm.mostPred]=max(max(localPred,[],2));
        if prm.mostPred==bci.leftEvent && dummy>bci.paradigm.fbPredRate, % move left
            prm.direction=bci.paradigm.fbVelocityToDestination;
            if prm.armSystemVal==1,
                prm.movSystem = 1;
            else
                prm.movSystem = 3;
            end
            prm.correctDir = prm.curEvent==bci.leftEvent;
            prm.trialClassified = true;
            disp(num2str(prm.predictedInTrial));
        elseif prm.mostPred==bci.rightEvent && dummy>bci.paradigm.fbPredRate, % move right
            prm.direction=bci.paradigm.fbVelocityToDestination;
            if prm.armSystemVal==1,
                prm.movSystem = 4;
            else
                prm.movSystem = 0;
            end
            prm.correctDir = prm.curEvent==bci.rightEvent;
            prm.trialClassified = true;
            disp(num2str(prm.predictedInTrial));
        else  % ignore baseline in this version
            prm.movSystem=prm.armSystemVal; % don't move
            prm.direction=0;
            prm.mostPred=0;
        end
        setArmSystem(prm.movSystem);
        setDirection(prm.direction);
    elseif prm.mode==0 && ~prm.hitTarget && any(prm.curEvent==[bci.leftEvent bci.rightEvent]), % move in train run
        if prm.armSystemVal==1 && prm.curEvent==bci.leftEvent,
            prm.movSystem = 1;
        elseif prm.armSystemVal==1 && prm.curEvent==bci.rightEvent,
            prm.movSystem = 4;
        elseif prm.armSystemVal==0 && prm.curEvent==bci.leftEvent,
            prm.movSystem = 3;
        elseif prm.armSystemVal==0 && prm.curEvent==bci.rightEvent,
            prm.movSystem = 0;
        end
        setArmSystem(prm.movSystem);
        setDirection(bci.paradigm.stimVelocityToDestination); % double velocity
        prm.trialClassified=true;
        prm.correctDir=true;
    else
        prm.mostPred=0;
    end
    currentArmPosition=getPosition;
    prm.hitTarget = currentArmPosition>9995 || prm.curEvent==bci.baseEvent;%currentArmPosition<2600;
    prm.hitSuccess = currentArmPosition>9995 && prm.correctDir;
elseif strcmp(action,'init'),
    prm.armSystemVal=2;
    prm.ballSystemVal=2;
    prm.armPos=5000;
    prm.restingVal=1e-12;% currently restingVal=0 doesn't work properly

    setArmSystem(prm.armSystemVal);
    setBallSystem(prm.ballSystemVal);
    setDirection(prm.restingVal);
    setPosition(prm.armPos);
    % wait until position is set
    while abs(getPosition-prm.armPos)>10,pause(0.001);end    
    if strcmpi(bci.stimulation.armSystem,'left'),
        prm.armSystemVal = 0;
    else % assume right arm system
        prm.armSystemVal = 1;
    end
    if prm.mode==1,
        prm.systemRorL([bci.leftEvent bci.rightEvent])=[1 0];
        prm.mostPred=2;
        % number of samples to get local true positives
        prm.nPredLocal = floor(bci.paradigm.fbPredictionWindow*bci.param.winsrate);
        prm.localPredCount=1;
        prm.correctDir=false;
    end
    prm.trialClassified = false;
elseif strcmp(action,'newevent')
    switch prm.curEvent,
        case bci.leftEvent,
            prm.targetBall=1;
            setBallSystem(-1);
            setArmSystem(prm.armSystemVal);
            setColor(prm.targetBall,bci.stimulation.targetColor(1),bci.stimulation.targetColor(2),bci.stimulation.targetColor(3));
            setColor(0 ,0, 0, 0);
        case bci.rightEvent,
            prm.targetBall=0;
            setArmSystem(prm.armSystemVal);
            setBallSystem(-1);
            setColor(prm.targetBall,bci.stimulation.targetColor(1),bci.stimulation.targetColor(2),bci.stimulation.targetColor(3));
            setColor(1 ,0, 0, 0);
        case bci.baseEvent,
            setBallSystem(-1);
            setArmSystem(prm.armSystemVal);
            setColor(0 ,0, 0, 0);
            setColor(1 ,0, 0, 0);
        otherwise
            setBallSystem(2);
            setArmSystem(2);
    end
    setDirection(prm.restingVal);    
    setPosition(prm.armPos);    
    prm.hitTarget=bci.paradigm.stimVelocityToDestination==0;
    prm.trialClassified = false;
    % wait until position is set
    while abs(getPosition-prm.armPos)>10,pause(0.001);end
elseif strcmp(action,'newtarget')
    prm.armPos=5000;
    prm.targetBall = prm.systemRorL(prm.curEvent);
    % set new target
    setDirection(prm.restingVal);
    setPosition(prm.armPos);
    % wait until position is set
    while abs(getPosition-prm.armPos)>10,pause(0.001);end    
    setArmSystem(prm.armSystemVal);
    setBallSystem(-1);
    setColor(prm.targetBall ,bci.stimulation.targetColor(1),bci.stimulation.targetColor(2),bci.stimulation.targetColor(3));
    setColor(1-prm.targetBall ,0, 0, 0);
    prm.localPredCount=1;
    prm.trialClassified = false;
    prm.correctDir = false;
elseif strcmp(action,'hide')
    setColor(0 ,0, 0, 0);
    setColor(1 ,0, 0, 0);
    setDirection(prm.restingVal);
    setArmSystem(2);
    setBallSystem(2);
    setPosition(5000);
    % wait until position is set
    while abs(getPosition-5000)>10,pause(0.001);end
elseif strcmp(action,'finish')
    setColor(0 ,0, 0, 0);
    setColor(1 ,0, 0, 0);
    setArmSystem(2);
    setBallSystem(2);
end

% ------- Robotarm event evoked control one target only
function prm=bciParadigmID4(bci,action,prm)
if strcmp(action,'move'),
    if prm.curEvent == 6,
        prm.hitTarget=false;
        prm.mostPred = 0;
        return
    end
    if prm.mode>0 && length(prm.predictedInTrial)>=prm.nPredLocal&&~prm.trialClassified,
        % determine prediction rate of trial
        predCount(bci.leftEvent)=sum(prm.predictedInTrial==bci.leftEvent);
        predCount(bci.baseEvent)=sum(prm.predictedInTrial==bci.baseEvent);
        predCount(bci.rightEvent)=sum(prm.predictedInTrial==bci.rightEvent);
        [dummy, prm.mostPred]=max(predCount);
        if sum(dummy==predCount)>1, % what if number of predictions is equal?
            prm.mostPred = 0;
        else
            disp(num2str(prm.predictedInTrial));
        end
        if prm.mostPred==bci.leftEvent% && dummy>bci.paradigm.fbPredRate, % move left
            prm.direction=bci.paradigm.fbVelocityToDestination;
            if prm.armSystemVal==1,
                prm.movSystem = 1;
            else
                prm.movSystem = 3;
            end
            prm.correctDir = prm.curEvent==bci.leftEvent;
            prm.trialClassified = true;
        elseif prm.mostPred==bci.rightEvent% && dummy>bci.paradigm.fbPredRate, % move right
            prm.direction=bci.paradigm.fbVelocityToDestination;
            if prm.armSystemVal==1,
                prm.movSystem = 4;
            else
                prm.movSystem = 0;
            end
            prm.correctDir = prm.curEvent==bci.rightEvent;
            prm.trialClassified = true;
        elseif prm.mostPred==bci.baseEvent% && dummy>bci.paradigm.fbPredRate, % move back
            prm.direction = -bci.paradigm.fbVelocityToDestination;
            prm.movSystem=prm.armSystemVal; % 
            prm.correctDir = prm.curEvent==bci.baseEvent;
            prm.trialClassified = true;
        else
            prm.movSystem=prm.armSystemVal; % don't move
            prm.direction=0;
            prm.mostPred=0;
        end
        setDirection(prm.direction);
        setArmSystem(prm.movSystem);
    elseif prm.mode==0 && ~prm.hitTarget && (prm.curEvent>0), % move in train run
        dirVel = bci.paradigm.stimVelocityToDestination;
        if prm.armSystemVal==1 && prm.curEvent==bci.leftEvent,
            prm.movSystem = 1;
        elseif prm.armSystemVal==1 && prm.curEvent==bci.rightEvent,
            prm.movSystem = 4;
        elseif prm.armSystemVal==0 && prm.curEvent==bci.leftEvent,
            prm.movSystem = 3;
        elseif prm.armSystemVal==0 && prm.curEvent==bci.rightEvent,
            prm.movSystem = 0;
        elseif prm.curEvent==bci.baseEvent,
            prm.movSystem=prm.armSystemVal;
            dirVel=-bci.paradigm.stimVelocityToDestination;
        end
        setArmSystem(prm.movSystem);
        setDirection(dirVel); % double velocity
        prm.trialClassified=true;
        prm.correctDir=true;
    else
        prm.mostPred=0;
    end
    currentArmPosition=getPosition;
    prm.hitTarget = currentArmPosition>9995 || currentArmPosition<2400;
    prm.hitSuccess = prm.correctDir;
elseif strcmp(action,'init'),
    prm.armSystemVal=2; % hide arm
    prm.ballSystemVal=2; % hide ball
    prm.armPos=5000; % arm down
    prm.restingVal=1e-12;% currently restingVal=0 doesn't work properly

    setArmSystem(prm.armSystemVal);
    setBallSystem(prm.ballSystemVal);
    setDirection(prm.restingVal);
    setPosition(prm.armPos);
    if strcmpi(bci.stimulation.armSystem,'left'),
        prm.armSystemVal = 0;
    else % assume right arm system
        prm.armSystemVal = 1;
    end
    if prm.mode==1,
        % set ball system for each direction
        prm.systemRorL([bci.leftEvent bci.rightEvent])=[1 0];
        prm.mostPred=bci.baseEvent; % 
        % number of samples to get local true positives
        prm.nPredLocal = floor(bci.paradigm.fbPredictionWindow*bci.param.winsrate);
        prm.localPredCount=1;
        prm.correctDir=false;
    end
    if any(bci.eventsToClassify == bci.leftEvent),
        prm.targetBall = 1;
    else
        prm.targetBall = 0;
    end
    prm.trialClassified = false;
    % wait until position is set
    while abs(getPosition-prm.armPos)>10,pause(0.001);end    
elseif strcmp(action,'newevent')
    setArmSystem(2);
    setBallSystem(2);
    setDirection(prm.restingVal);
    setPosition(prm.armPos);
    % wait until position is set
    while abs(getPosition-prm.armPos)>10,pause(0.001);end        
    switch prm.curEvent,
        case bci.leftEvent,
            prm.targetBall=1;
            setBallSystem(prm.targetBall);
            setArmSystem(prm.armSystemVal);
            setColor(prm.targetBall,bci.stimulation.targetColor(1),bci.stimulation.targetColor(2),bci.stimulation.targetColor(3));
        case bci.rightEvent,
            prm.targetBall=0;
            setArmSystem(prm.armSystemVal);
            setBallSystem(prm.targetBall);
            setColor(prm.targetBall,bci.stimulation.targetColor(1),bci.stimulation.targetColor(2),bci.stimulation.targetColor(3));
        case bci.baseEvent,
            setArmSystem(prm.armSystemVal);
            setBallSystem(prm.targetBall);
            setColor(prm.targetBall ,bci.stimulation.targetColor(4),bci.stimulation.targetColor(5),bci.stimulation.targetColor(6));
        case 6,
            % attention event
            setArmSystem(prm.armSystemVal);
            setBallSystem(prm.targetBall);
            setColor(prm.targetBall ,0, 0, 0); % yellow ( default color)            
        otherwise
            setBallSystem(2);
            setArmSystem(2);
    end
    prm.hitTarget=bci.paradigm.stimVelocityToDestination==0; %hitTarget is always true if stimVelocityToDestination is zero (no Freedback)
    prm.trialClassified = false;
elseif strcmp(action,'newtarget')
    prm.armPos=5000;
    % set new target
    setDirection(prm.restingVal);
    setPosition(prm.armPos);
    % wait until position is set
    while abs(getPosition-prm.armPos)>10,pause(0.001);end    
    setArmSystem(prm.armSystemVal);
    setBallSystem(prm.targetBall);
    if prm.curEvent==bci.baseEvent,
        setColor(prm.targetBall ,bci.stimulation.targetColor(4),bci.stimulation.targetColor(5),bci.stimulation.targetColor(6));
    elseif prm.curEvent==6; % attention event
        setColor(prm.targetBall ,0,0,0);        
    else
        setColor(prm.targetBall ,bci.stimulation.targetColor(1),bci.stimulation.targetColor(2),bci.stimulation.targetColor(3));
    end
    prm.localPredCount=1;
    prm.trialClassified = false;
    prm.correctDir = false;
elseif strcmp(action,'hide')
    setColor(0 ,0, 0, 0);
    setColor(1 ,0, 0, 0);
    setDirection(prm.restingVal);
    setArmSystem(2);
    setBallSystem(2);
    setPosition(5000);
    % wait until position is set
    while abs(getPosition-5000)>10,pause(0.001);end
elseif strcmp(action,'finish')
    setColor(0 ,0, 0, 0);
    setColor(1 ,0, 0, 0);
    setArmSystem(2);
    setBallSystem(2);
end